package com.effectiv.gooruda.rest.api.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.effectiv.gooruda.rest.api.domain.Cache;
import com.effectiv.gooruda.rest.api.domain.CacheEntry;
import com.effectiv.gooruda.rest.api.operation.CacheOperation;
import com.effectiv.gooruda.security.rest.RESTSecurityUtil;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.core.IMap;
import com.hazelcast.core.ISet;

@Slf4j
@Component
@Deprecated
public class CacheServiceImpl implements CacheOperation{
	
	@Autowired
	@Qualifier("client")
	private HazelcastClient client;
	
	
	
	@Override
	public Cache findOne(String cacheName) {
		IMap<String, CacheEntry> map = getMap(cacheName);
		
		
		Cache cache = null;
		
		if(map != null){
			cache = BeanUtils.instantiate(Cache.class);
			cache.setName(cacheName);
			cache.setSize(map.size());
			cache.setId(map.getId().toString());
		}
		return cache;
	}

	@Override
	public void addEntry(String cacheName, String key, CacheEntry entry) {
		IMap<String, CacheEntry> map = getMap(cacheName);
				
		long timeout = entry.getTtl();
		
		Object o = entry.getValue();
		
		log.debug("o = {}", o);
		log.debug("o = {}", o.getClass());
		
		if(o instanceof Integer){
			Integer i = (Integer)o;
			log.debug("Integer value = {}", i);
			
			entry.setValue(new AtomicInteger(i));
		}
		
		map.put(key, entry, timeout, TimeUnit.SECONDS);
	}

	@Override
	public CacheEntry getEntry(String cacheName, String key) {
		IMap<String,CacheEntry> map = getMap(cacheName);
		CacheEntry entry = map.get(key);
		return entry;
	}
	
	

	@Override
	public Cache delete(String cacheName) {
		IMap<String,CacheEntry> map = getMap(cacheName);
		Cache cache = null;
		
		if(map != null){
			cache = BeanUtils.instantiate(Cache.class);
			cache.setName(cacheName);
			cache.setSize(map.size());
			cache.setId(map.getId().toString());
		
			map.destroy();
			
		}
		
		return cache;
	}
	
	

	@Override
	public void clear(String cacheName) {
		IMap<String,CacheEntry> map = getMap(cacheName);
		map.clear();
	}
	
	@Override
	public CacheEntry removeEntry(String cacheName, String key) {
		IMap<String,CacheEntry> map = getMap(cacheName);
		return map.remove(key);		
	}

	@Override
	public CacheEntry increment(String cacheName, String key) {
		IMap<String,CacheEntry> map = getMap(cacheName);
		
		log.debug("Map = {}", map);
		
		CacheEntry entry = map.get(key);
		
		log.debug("entry = {}", entry);
		
		log.debug("value = {}", entry.getValue());
		
		((AtomicInteger)entry.getValue()).addAndGet(1);
		map.put(key, entry);
		
		return entry;
	}

	//@Override
	public List<Cache> listCaches() {
		ISet<String> set = client.getSet(RESTSecurityUtil.getApplication().getId());
		
		Iterator<String> i = set.iterator();
		
		List<Cache> caches = new ArrayList<Cache>();
		
		while(i.hasNext()){
			caches.add(findOne(i.next()));
		}
		
		return caches;
	}

	private IMap<String, CacheEntry> getMap(String cacheName){
		String appCacheName = RESTSecurityUtil.getApplication().getId() + "." + cacheName;
		
		IMap<String, CacheEntry> map = client.getMap(appCacheName);
		log.debug("Got map = {}", map);
		
		
		return map;
	}
}
